import {format} from 'quasar';
import axios from 'axios';

const {pad} = format;
const diffName = ['Easy', 'Normal', 'Hard', 'Expert', 'Special'];
export {diffName};

let serverOrigin = ['http://120.92.174.173/bestdori', 'https://bestdori.reikohaku.fun', 'https://bd.reikohaku.fun', 'https://bestdori.fr.reikohaku.fun'];
let serverList = ['jp', 'en', 'tw', 'cn', 'kr'];

async function getBestdoriApiData(url) {
  //给两个允许跨域的服务器源，就算其中一个故障或者暂时关闭，服务也能正常运转
  //有没有好心人捐一个高速代理服务器啊QAQ
  for (let i in serverOrigin) {
    try {
      let {data} = await axios.get(`${serverOrigin[i]}/${url}`);
      if (data) return data;
    } catch (e) {
    }
  }
  return null;
}

async function postBestdoriApiData(url, post) {
  //给两个允许跨域的服务器源，就算其中一个故障或者暂时关闭，服务也能正常运转
  //有没有好心人捐一个高速代理服务器啊QAQ
  for (let i in serverOrigin) {
    try {
      let {data} = await axios.post(`${serverOrigin[i]}/${url}`, post);
      if (data) return data;
    } catch (e) {
    }
  }
  return null;
}

export async function getCommunityChart(id, loadingText) {
  if (loadingText) loadingText.text = 'play.load.gettingChartInfo';
  let data = await getBestdoriApiData(`api/post/details?id=${id}`);
  if (data.result) {
    if (data.post.categoryId === 'chart') {
      if (loadingText) loadingText.text = 'play.load.resolvingData';
      let response = {
        id: id,
        type: 'community',
        title: data.post.title,
        artist: data.post.artists,
        author: data.post.author.nickname ? data.post.author.nickname : data.post.author.username,
        difficulty: [{
          type: diffName[data.post.diff],
          level: data.post.level,
          notes: data.post.notes.filter(function (currentValue) {
            return currentValue.type === 'Note'
          }).length,
          label: diffName[data.post.diff],
          value: diffName[data.post.diff]
        }],
        audio: (await getCommunityAudio(data.post.song, loadingText)).valueOf(),
        cover: (await getCommunityCover(data.post.song, loadingText)).valueOf(),
        notes: data.post.notes
      };
      return response;
    } else throw new Error('ERR_NOT_A_CHART');
  } else throw new Error('ERR_GET_DATA_FAILED');
  ;
}

async function getCommunityAudio(songInfo, loadingText) {
  switch (songInfo.type) {
    case 'custom':
      return songInfo.audio;
    case 'bandori':
      return (await getOfficialChartInfo(songInfo.id, 'zh_cn', loadingText)).audio;
    case 'llsif':
      return `https://card.llsif.moe/asset/${await getSifInfo(songInfo.id).mp3}`;
    case 'osu':
      return `https://beatconnect.io/audio/${songInfo.id}/${songInfo.diff}/`;
    default:
      return ''
  }
}

async function getCommunityCover(songInfo, loadingText) {
  switch (songInfo.type) {
    case 'custom':
      return songInfo.cover;
    case 'bandori':
      return (await getOfficialChartInfo(songInfo.id, 'zh_cn', loadingText)).cover;
    case 'llsif':
      return `https://card.llsif.moe/asset/${await getSifInfo(songInfo.id).cover}`;
    case 'osu':
      return `https://assets.ppy.sh/beatmaps/${songInfo.id}/covers/cover.jpg`;
    default:
      return ''
  }
}

async function getSifInfo(id) {
  let data = await getBestdoriApiData('api/misc/llsif.5.json');
  if (data) return data[id];
  else throw new Error('ERR_NO_LLSIF_SONG_DATA');
}

export async function getOfficialChartInfo(id, lang, loadingText) {
  let langId = ({
    ja_jp: 0,
    en_us: 1,
    zh_tw: 2,
    zh_cn: 3,
    ko_kr: 4
  })[lang] || lang;
  if (!langId) langId = 0;
  if (loadingText) loadingText.text = 'play.load.gettingChartInfo';
  let data = await getBestdoriApiData(`api/songs/${id}.json`);
  if (data) {
    if (loadingText) loadingText.text = 'play.load.resolvingData';
    let assetServer;
    for (let i = 0; i < data.publishedAt.length; i++) {
      if (data.publishedAt[i]) {
        assetServer = serverList[i];
        break;
      }
    }
    let response = {
      id: id,
      type: 'official',
      title: data.musicTitle[langId] ? data.musicTitle[langId] : getFirstNotNull(data.musicTitle),
      artist: await getBandNameById(data.bandId, langId),
      difficulty: getDifficultyList(data),
      audio: getOfficialAudio(id, assetServer),
      cover: getOfficialCover(id, data.jacketImage[0], assetServer)
    };
    return response;
  } else throw new Error('ERR_GET_DATA_FAILED');
}

async function getBandNameById(id, lang) {
  let band = await getBestdoriApiData(`api/bands/all.1.json`);
  if(band[id]) {
    if(lang === undefined) return band[id].bandName;
    else return band[id].bandName[lang] ? band[id].bandName[lang] : getFirstNotNull(band[id].bandName);
  } else return (lang === undefined ? ['Unknown Artist'] : 'Unknown Artist');
}

function getOfficialAudio(id, assetServer) {
  return `https://bestdori.com/assets/${assetServer}/sound/bgm${pad(id.toString(), 3)}_rip/bgm${pad(id.toString(), 3)}.mp3`;
}

function getOfficialCover(id, jacketImage, assetServer) {
  if (assetServer === 'en') return `https://bestdori.com/assets/en/musicjacket/${jacketImage}_rip/jacket.png`
  else {
    let num = (Math.floor(id / 10) === id / 10) ? id / 10 : Math.floor(id / 10) + 1;
    num *= 10;
    return `https://bestdori.com/assets/${assetServer}/musicjacket/musicjacket${num}_rip/assets-star-forassetbundle-startapp-musicjacket-musicjacket${num}-${jacketImage}-jacket.png`;
  }
}

function getDifficultyList(data) {
  let list = [];
  for (let item in data.difficulty) {
    let diff = {
      type: diffName[list.length],
      level: data.difficulty[item].playLevel,
      notes: data.notes ? data.notes[item] : 0,
      label: diffName[list.length],
      value: diffName[list.length]
    };
    list.push(diff);
  }
  return list;
}

export async function getOfficialChart(id, diff, loadingText) {
  if (loadingText) loadingText.text = 'play.load.gettingChartData';
  let data = await getBestdoriApiData(`api/songs/chart/${id}.${diff.toLowerCase()}.json`);
  if (data) return data;
  else throw new Error('ERR_GET_DATA_FAILED')
}

export async function getOfficialSongList() {
  let data = await getBestdoriApiData(`api/songs/all.5.json`);
  let response = [];
  if (data) {
    let length = 0, count = 0;
    for (const i in data) length++;
    for (const i in data) {
      let assetServer;
      for (let j = 0; j < data[i].publishedAt.length; j++) {
        if (data[i].publishedAt[j]) {
          assetServer = serverList[j];
          break;
        }
      }
      let song = {
        id: i,
        title: data[i].musicTitle,
        artist: await getBandNameById(data[i].bandId),
        publishTime: data[i].publishedAt,
        difficulty: getDifficultyList(data[i]),
        cover: getOfficialCover(i, data[i].jacketImage[0], assetServer)
      }
      response.push(song);
      count++;
    }
    return response;
  } else throw new Error('ERR_GET_DATA_FAILED')
}

function getFirstNotNull(arr) {
  for(let i in arr) if(arr[i] != null) return arr[i];
  return arr[0];
}

export async function searchCommunityChart(page, search, tags) {
  //就写死了一页20个吧，不想再多了
  let offset = page ? page * 20 : 0;
  let post = {
    categoryId: 'chart',
    categoryName: 'SELF_POST',
    following: false,
    limit: 20,
    offset, order: 'TIME_DESC',
    search, tags
  };
  let data = await postBestdoriApiData(`api/post/list`, post);
  if (!data) throw new Error('ERR_GET_DATA_FAILED');
  let list = [];
  data.posts.forEach(item => {
    list.push({
      id: item.id,
      title: item.title,
      artist: item.artists,
      author: item.nickname ? item.nickname : item.username,
      difficulty: [{
        type: diffName[item.diff],
        level: item.level,
        label: diffName[item.diff],
        value: diffName[item.diff]
      }],
      tags: item.tags
    });
  });
  return {count: data.count, list};
}
